package com.xj.shop.manage.all.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.extra.mail.MailUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xj.shop.client.all.model.LoginUserDTO;
import com.xj.shop.client.all.model.RegisterUserDTO;
import com.xj.shop.manage.all.mapper.UserMapper;
import com.xj.shop.manage.all.model.dto.UserDTO;
import com.xj.shop.manage.all.model.entity.User;
import com.xj.shop.manage.all.model.query.UserQuery;
import com.xj.shop.manage.all.model.vo.UserVO;
import com.xj.shop.manage.all.service.UserService;
import io.github.wslxm.springbootplus2.common.auth.entity.JwtUser;
import io.github.wslxm.springbootplus2.common.auth.util.JwtUtil;
import io.github.wslxm.springbootplus2.common.auth.util.Md5Util;
import io.github.wslxm.springbootplus2.core.base.service.impl.BaseServiceImpl;
import io.github.wslxm.springbootplus2.core.config.error.ErrorException;
import io.github.wslxm.springbootplus2.core.enums.Base;
import io.github.wslxm.springbootplus2.core.result.ResultType;
import io.github.wslxm.springbootplus2.core.utils.BeanDtoVoUtil;
import io.github.wslxm.springbootplus2.core.utils.id.IdUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * 工具--用户表 ServiceImpl
 *
 * <p>
 * ::本代码由[兮家小二]提供的代码生成器生成,如有问题,请手动修改 ::作者CSDN:https://blog.csdn.net/qq_41463655
 * </p>

 * @author ws
 * @email 1720696548@qq.com
 * @date 2022-08-24 11:17:09
 */
@Service
@Slf4j
public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implements UserService {

    /**
     * 邮件验证码保存
     */
    static Map<String, String> eamilCodeMap = new ConcurrentHashMap();

    @Override
    public IPage<UserVO> findPage(UserQuery query) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>()
                .likeRight(StringUtils.isNotBlank(query.getUsername()), User::getUsername, query.getUsername())
                .likeRight(StringUtils.isNotBlank(query.getEmail()), User::getEmail, query.getEmail())
                .eq(query.getGender() != null, User::getGender, query.getGender())
                .likeRight(StringUtils.isNotBlank(query.getPhone()), User::getPhone, query.getPhone())
                .likeRight(StringUtils.isNotBlank(query.getNickname()), User::getNickname, query.getNickname())
                .likeRight(StringUtils.isNotBlank(query.getFullName()), User::getFullName, query.getFullName())
                .eq(query.getRegTime() != null, User::getRegTime, query.getRegTime())
                .eq(query.getDisable() != null, User::getDisable, query.getDisable())
                .orderByDesc(User::getCreateTime);
        Page<User> page = this.page(new Page<>(query.getCurrent(), query.getSize()), queryWrapper);
        return BeanDtoVoUtil.pageVo(page, UserVO.class);
    }

    @Override
    public UserVO findId(String id) {
        return BeanDtoVoUtil.convert(this.getById(id), UserVO.class);
    }

    @Override
    public String insert(UserDTO dto) {
        User entity = dto.convert(User.class);
        boolean b = this.save(entity);
        return entity.getId();
    }

    @Override
    public boolean upd(String id, UserDTO dto) {
        User entity = dto.convert(User.class);
        entity.setId(id);
        return this.updateById(entity);
    }

    @Override
    public boolean del(String id) {
        return this.removeById(id);
    }


    @Override
    public String register(RegisterUserDTO dto) {
        if (verifyEmailRegister(dto.getEmail())) {
            throw new ErrorException(ResultType.PARAM_ERROR.getValue(), "邮箱已被注册");
        }
        if (verifyUsernameRegister(dto.getUsername())) {
            throw new ErrorException(ResultType.PARAM_ERROR.getValue(), "账号已被注册");
        }
        // 验证码
        if (!eamilCodeMap.containsKey(dto.getEmail()) || !eamilCodeMap.get(dto.getEmail()).equals(dto.getEmailCode())) {
            throw new ErrorException(ResultType.PARAM_ERROR.getValue(), "没有发送邮件验证或验证码错误");
        }
        // 开始注册
        User toolUser = dto.convert(User.class);
        toolUser.setId(IdUtil.snowflakeId());
        toolUser.setDisable(Base.Disable.V0.getValue());
        toolUser.setRegTime(LocalDateTime.now());
        toolUser.setPassword(Md5Util.encode(dto.getPassword(),toolUser.getId()));
        toolUser.setHeadPic("https://tva3.sinaimg.cn/large/0072Vf1pgy1foxkizc9w8j31kw0w0e45.jpg");
        this.save(toolUser);
        return toolUser.getId();
    }


    @Override
    public synchronized Boolean login(LoginUserDTO dto) {
        // 1、判断账号
        User toolUser = this.getOne(new LambdaQueryWrapper<User>()
                .and(i -> i.eq(StringUtils.isNotBlank(dto.getUsername()), User::getEmail, dto.getUsername())
                        .or().eq(StringUtils.isNotBlank(dto.getUsername()), User::getUsername, dto.getUsername()))
        );
        if (toolUser == null) {
            throw new ErrorException(ResultType.LOGIN_IS_NO_ACCOUNT);
        }
        // 2、判断密码
        if (!toolUser.getPassword().equals(Md5Util.encode(dto.getPassword(),toolUser.getId()))) {
            throw new ErrorException(ResultType.LOGIN_ERROR_USER_PASSWORD);
        }
        if (toolUser.getDisable().equals( Base.Disable.V1)) {
            throw new ErrorException(ResultType.LOGIN_IS_NO_DISABLE);
        }
        // 登录成功 生成jwt
        JwtUser jwtUser = new JwtUser();
        jwtUser.setUserId(toolUser.getId());
        jwtUser.setFullName(toolUser.getNickname());
        jwtUser.setType(JwtUtil.userType[1]);
        // 设置token有效期(分)
        jwtUser.setExpiration(60 * 24 * 15);
        // 添加权限 和 权限数据版本号,当权限发生改变时，直接刷新token信息
        JwtUtil.createToken(jwtUser, response);

        // 刷新最后登录时间
        User updToolUser = new User();
        updToolUser.setId(toolUser.getId());
        updToolUser.setEndTime(LocalDateTime.now());
        this.updateById(updToolUser);
        return true;
    }


    @Override
    public synchronized Boolean sendEmailAuthCode(String email) {
        // 验证邮箱是否已经注册
        if (verifyEmailRegister(email)) {
            throw new ErrorException(ResultType.PARAM_ERROR.getValue(), "邮箱已被注册");
        }
        String emailCode = RandomUtil.randomNumbers(4);
        try {
            String res = MailUtil.send(email, "兮家APP", "邮件来自兮家商城DEMO,你的验证码为:" + emailCode, false);
            eamilCodeMap.put(email, emailCode);
            log.info("兮家-APP邮件验证码:{} ,发送结果:", emailCode,res);
            return true;
        } catch (Exception e) {
            throw new ErrorException(ResultType.SYS_ERROR_CODE_500.getValue(), "邮件发送失败");
        }
    }


    /**
     * 验证邮箱是否已经注册
     * @return true 已注册  false 未注册
     */
    private boolean verifyEmailRegister(String email) {
        long count = this.count(new LambdaQueryWrapper<User>().eq(User::getEmail, email));
        return count > 0;
    }

    /**
     * 验证账号是否已经注册
     * @return true 已注册  false 未注册
     */
    private boolean verifyUsernameRegister(String username) {
        long count = this.count(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
        return count > 0;
    }

}
